package com.scs.application.modules.wm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.consts.SerialKeys;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.DateUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.core.utils.UserUtils;
import com.scs.application.modules.base.service.WarehouseService;
import com.scs.application.modules.cfg.utils.ParameterUtils;
import com.scs.application.modules.dept.mapper.DeptReturnMapper;
import com.scs.application.modules.dept.mapper.OprtUseMapper;
import com.scs.application.modules.dept.mapper.UseMapper;
import com.scs.application.modules.sys.model.RestResult;
import com.scs.application.modules.thirdparty.dto.HrpStockItemDTO;
import com.scs.application.modules.thirdparty.service.HrpService;
import com.scs.application.modules.wm.entity.*;
import com.scs.application.modules.wm.mapper.DistMapper;
import com.scs.application.modules.wm.mapper.StockCheckMapper;
import com.scs.application.modules.wm.mapper.TransferMapper;
import com.scs.application.modules.wm.mapper.WorkOrderMapper;
import com.scs.application.modules.wm.service.StockCheckItemService;
import com.scs.application.modules.wm.service.StockCheckService;
import com.scs.application.modules.wm.service.StockService;
import com.google.common.collect.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 */
@Service
public class StockCheckServiceImpl extends BaseServiceImpl<StockCheckMapper, StockCheck> implements StockCheckService {

    @Autowired
    private StockCheckItemService stockCheckItemService;

    @Autowired
    private StockService stockService;

    @Autowired
    private HrpService hrpService;

    @Autowired
    private WarehouseService warehouseService;

    @Autowired
    private DistMapper distMapper;

    @Autowired
    private TransferMapper transferMapper;

    @Autowired
    private UseMapper useMapper;

    @Autowired
    private OprtUseMapper oprtUseMapper;

    @Autowired
    private DeptReturnMapper deptReturnMapper;

    @Autowired
    private WorkOrderMapper workOrderMapper;

    @Value("${system.hrp.url}")
    String url;
    @Value("${system.hrp.driver-class-name}")
    String driverClassName;
    @Value("${system.hrp.username}")
    String username;
    @Value("${system.hrp.password}")
    String password;

    @Override
    public boolean saveOrUpdate(StockCheck entity) {
        if (StringUtils.isBlank(entity.getBusKey())) {
            entity.setBusKey(serialRuleAdapter.getSerialRuleService().generateCode(SerialKeys.STOCK_CHECK));
        }
        if (StringUtils.isBlank(entity.getBusUser())) {
            entity.setBusUser(UserUtils.currentUser().getName());
        }
        if (entity.getFlagFinished() == null ||entity.getFlagFinished() != true) {
            List<StockCheck> list = this.list(Wrappers.<StockCheck>query().eq("warehouse_id",entity.getWarehouseId()).eq("flag_finished", false));
            if(list != null && list.size() > 0) {
                throw  new BusinessException("该仓库已有盘点单，请勿重复盘点");
            }
        }
        if (StringUtils.isBlank(entity.getId())) {
            QueryWrapper queryWrapper = new QueryWrapper<Stock>().eq("warehouse_id",entity.getWarehouseId()).gt("sku_qty", 0);
            if (StringUtils.isNotBlank(entity.getLocationId())) queryWrapper.eq("location_id",entity.getLocationId());
            if (StringUtils.isNotBlank(entity.getMatrId())) queryWrapper.eq("matr_id",entity.getMatrId());
            if (StringUtils.isNotBlank(entity.getCheckType()) && !GlobalConsts.CheckType.all.equals(entity.getCheckType())) {
                String busDateBegin=null;
                String busDateEnd=null;
                String dateStr;
                String checkType="";
                switch (entity.getCheckType()){
                    case GlobalConsts.CheckType.today: //今天库存变动
                        checkType="今天库存变动";
                         dateStr = DateUtils.format(new Date(),"yyyy-MM-dd");
                        busDateBegin=dateStr+" 00:00:00";
                        busDateEnd=dateStr+" 23:59:59";
                        break;
                    case GlobalConsts.CheckType.yesterday: //昨天库存变动
                        checkType="昨天库存变动";
                         dateStr = DateUtils.format(DateUtils.addDays(new Date(), -1),"yyyy-MM-dd");
                        busDateBegin=dateStr+" 00:00:00";
                        busDateEnd=dateStr+" 23:59:59";
                        break;
                    case GlobalConsts.CheckType.thisWeek: //本周库存变动
                        checkType="本周库存变动";
                         dateStr = DateUtils.format(DateUtils.getFirstDayOfWeek(new Date()),"yyyy-MM-dd");
                        busDateBegin=dateStr+" 00:00:00";
                        dateStr = DateUtils.format(DateUtils.getLastDayOfWeek(new Date()),"yyyy-MM-dd");
                        busDateEnd=dateStr+" 23:59:59";
                        break;
                    case GlobalConsts.CheckType.thisMonth: //本月库存变动
                        checkType="本月库存变动";
                        dateStr = DateUtils.format(DateUtils.getFirstDayOfMonth(new Date()),"yyyy-MM-dd");
                        busDateBegin=dateStr+" 00:00:00";
                        dateStr = DateUtils.format(DateUtils.getLastDayOfMonth(new Date()),"yyyy-MM-dd");
                        busDateEnd=dateStr+" 23:59:59";
                        break;
                    case GlobalConsts.CheckType.lastMonth: //上月库存变动
                        checkType="上月库存变动";
                        //上月第一天
                        Date dateLastMonth = DateUtils.getFirstDayOfMonth(DateUtils.addMonth(new Date(), -1)) ;
                        dateStr = DateUtils.format(DateUtils.getFirstDayOfMonth(dateLastMonth),"yyyy-MM-dd");
                        busDateBegin=dateStr+" 00:00:00";
                        dateStr = DateUtils.format(DateUtils.getLastDayOfMonth(dateLastMonth),"yyyy-MM-dd");
                        busDateEnd=dateStr+" 23:59:59";
                        break;
                    default:
                        throw  new BusinessException("未实现的盘点类型【%s】",entity.getCheckType());
                }

                QueryWrapper wrapper = Wrappers.<WorkOrder>query();
                wrapper.between("bus_date",busDateBegin,busDateEnd);
                wrapper.eq("warehouse_id",entity.getWarehouseId());
                if (StringUtils.isNotBlank(entity.getLocationId())) wrapper.eq("location_id",entity.getLocationId());
                if (StringUtils.isNotBlank(entity.getMatrId())) wrapper.eq("matr_id",entity.getMatrId());
                List<WorkOrderItem> listItem= workOrderMapper.getListGroupByMatr(wrapper);
                if (listItem == null || listItem.size() < 1) {
                    String errMsg ="仓库【"+entity.getWarehouseName()+"】\n";
                    if (StringUtils.isNotBlank(entity.getLocationId())){
                        errMsg+="库位【"+entity.getLocationName()+"】\n";
                    }
                    if (StringUtils.isNotBlank(entity.getMatrId())) {
                        errMsg+="耗材【"+entity.getMatrName()+"】\n";
                    }
                    errMsg+="【"+checkType+"】";
                    throw new BusinessException(errMsg+"为0，无需盘点!");
                }

                queryWrapper.in("matr_id",listItem.stream().map(WorkOrderItem::getMatrId).collect(Collectors.toList()));
            }

            double stockNum = 0;
            List<Stock> stockList = stockService.list(queryWrapper);
            if (ParameterUtils.isStockcheckUseview()) { //HRP系统--实际是第三方的视图
                if (StringUtils.isBlank(entity.getLocationId())) throw new BusinessException("库位不能为空，请选择盘点的库位!");//库位对应的是对方的仓库代码
                if (StringUtils.isNotBlank(entity.getMatrId())) throw new BusinessException("手持PDA暂时不支持按耗材盘点，后续会完善该功能!");
                stockList = stockListFromOther(entity.getLocationId(),entity.getMatrId());
            }
            if (stockList == null || stockList.size() < 1){
                String errMsg ="仓库【"+entity.getWarehouseName()+"】\n";
                if (StringUtils.isNotBlank(entity.getLocationId())){
                    errMsg+="库位【"+entity.getLocationName()+"】\n";
                }
                if (StringUtils.isNotBlank(entity.getMatrId())) {
                    errMsg+="耗材【"+entity.getMatrName()+"】\n";
                }
                throw new BusinessException(errMsg+"未找到相关库存，无需盘点!");
            }
//            //有处于拣货中、已拣货、配送中的配送和调拨单据不可开始盘点
//            List<String> flowList = new ArrayList<>();
//            flowList.add("picking");
//            flowList.add("picked");
//            flowList.add("distributing");
//            List<Dist> dists = distMapper.selectList(Wrappers.<Dist>query().in("flow_status", flowList));
//            if(dists != null && dists.size() > 0) {
//                throw new BusinessException("有%s个配送单未处理完成，不可开始盘点!", dists.size());
//            }
//            List<Transfer> transfers = transferMapper.selectList(Wrappers.<Transfer>query().in("flow_status", flowList));
//            if(transfers != null && transfers.size() > 0) {
//                throw new BusinessException("有%s个调拨单未处理完成，不可开始盘点!", transfers.size());
//            }
//            //有处于制单、待审核中的配送和调拨单据不可开始盘点
//            List<String> statusList = new ArrayList<>();
//            statusList.add("start");
//            statusList.add("submit");
//            List<Use> uses = useMapper.selectList(Wrappers.<Use>query().in("flow_status", statusList));
//            if(uses != null && uses.size() > 0) {
//                throw new BusinessException("有%s个科室消耗单未处理完成，不可开始盘点!", uses.size());
//            }
//            List<OprtUse> oprtUses = oprtUseMapper.selectList(Wrappers.<OprtUse>query().in("flow_status", statusList));
//            if(oprtUses != null && oprtUses.size() > 0) {
//                throw new BusinessException("有%s个病人消耗单未处理完成，不可开始盘点!", oprtUses.size());
//            }
//            List<DeptReturn> deptReturns = deptReturnMapper.selectList(Wrappers.<DeptReturn>query().in("flow_status", statusList));
//            if(deptReturns != null && deptReturns.size() > 0) {
//                throw new BusinessException("有%s个科室退货单未处理完成，不可开始盘点!", deptReturns.size());
//            }
//            List<WorkOrder> outOrders = workOrderMapper.selectList(Wrappers.<WorkOrder>query().eq("bus_type", "OUT_SP").in("flow_status", statusList));
//            if(outOrders != null && outOrders.size() > 0) {
//                throw new BusinessException("有%s个供应商出库单未处理完成，不可开始盘点!", outOrders.size());
//            }
//            List<String> inTypes = new ArrayList<>();
//            inTypes.add("IN_ASN");
//            inTypes.add("IN_MANUAL");
//            inTypes.add("IN_PACKAGE");
//            inTypes.add("IN_INIT");
//            List<WorkOrder> inOrders = workOrderMapper.selectList(Wrappers.<WorkOrder>query().in("bus_type", inTypes).in("flow_status", statusList));
//            if(inOrders != null && inOrders.size() > 0) {
//                throw new BusinessException("有%s个入库单未处理完成，不可开始盘点!", inOrders.size());
//            }
            stockNum = stockList.size();//stream().mapToDouble(Stock::getPackageQty).sum();
            entity.setStockNum(stockNum).setStockLoss(0d).setStockSurplus(0d).setStockUnknown(stockNum).setStockNormal(0d);
            super.saveOrUpdate(entity);

            //初始化盘点明细列表
            List<StockCheckItem> itemAddList = Lists.newArrayList();
            stockList.stream().forEach(stock -> {
                StockCheckItem stockCheckItem = new StockCheckItem();
                BeanUtils.copyProperties(stock, stockCheckItem);
                stockCheckItem.setCheckId(entity.getId())
                        .setCheckStatus(-9)
                        .setStockId(stock.getId())
                        .setCheckId(entity.getId())
                        .setId(null);
                itemAddList.add(stockCheckItem);
            });
            stockCheckItemService.saveBatch(itemAddList);
        } else {
            if (entity.getFlagFinished() != null && entity.getFlagFinished()){
                StockCheck stockCheck = this.getById(entity.getId());
                if (stockCheck.getFlagFinished() != null && stockCheck.getFlagFinished()) {

                    throw new BusinessException("该盘点单已结束盘点，操作人：%s，操作时间：%s", stockCheck.getModifier(), stockCheck.getGmtModified());
                }
                stockCheckItemService.update(Wrappers.<StockCheckItem>update().set("check_status",-1)
                        .eq("check_id",entity.getId()).eq("check_status","-9"));
                int count = stockCheckItemService.count(Wrappers.<StockCheckItem>query()
                        .eq("check_status", "-1").eq("check_id", entity.getId()));
                entity.setStockLoss((double) count).setStockUnknown(0D);
                super.saveOrUpdate(entity);
            }
        }
        return true;
    }
    public List stockListFromOther(String locationId, String matrId) {
        if (StringUtils.isBlank(locationId)) return null;//库位对应的是对方的仓库代码
        DriverManagerDataSource dataSource = getDataSource();
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        String sql = "SELECT goods_opcode matr_code,matr_name,matr_spec,matr_unit sku_unit,warehouse_code location_id,package_qty,lot,exp_date,rfid  FROM VIEW_SPD_STOCK_MAIN WHERE warehouse_code = '" + locationId + "'";
        if (StringUtils.isNotBlank(matrId)) sql += sql + " and = '" + matrId + "'";
        List<Stock> stocks = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(Stock.class));
        return stocks;
    }
    private DriverManagerDataSource getDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(driverClassName);
        return dataSource;
    }

    @Override
    public RestResult scan(String uc, String checkId) {
        RestResult restResult = RestResult.ok();
        StockCheck stockCheck = this.getById(checkId);
        if (stockCheck ==  null) throw new BusinessException("所操作的盘点单不存在或者已被删除");
        if (stockCheck.getFlagFinished() != null && stockCheck.getFlagFinished()) throw new BusinessException("该盘点单【%s】已结束盘点，请勿重复操作",stockCheck.getBusKey());
        this.haveSn(uc);
        Stock stock = stockService.getStockByUniqueCode(uc);

        StockCheckItem stockCheckItem = new StockCheckItem();

        stockCheckItem.setCheckStatus(0);
        //盘点状态 0：正常 1：盘盈 -1：盘亏
        String  msg = "正常";
        int checkStatus= 0;
        if (stock ==null || stock.getPackageQty() < 1) { //无库存

            stockCheckItem.setCheckStatus(-1);
            if (stock != null) {
                int count = stockCheckItemService.count(Wrappers.<StockCheckItem>query().ne("check_status","-9").eq("check_id",checkId).eq("stock_id",stock.getId()));
                if (count >0) throw new BusinessException("该唯一码【%s】已盘点过，请勿重复操作",stock.getSn()== null ?stock.getRfid():stock.getSn());
//                stockCheckItem=StockCheckItemMapper.queryByUC(checkId,uc);
                stockCheckItem=stockCheckItemService.getOne(Wrappers.<StockCheckItem>query().eq("check_id",checkId).eq("stock_id",stock.getId()));
                if (stockCheckItem == null) {
                    stockCheckItem = new StockCheckItem();
                    BeanUtils.copyProperties(stock, stockCheckItem);
                }
                msg = "盘亏【无库存】";
                checkStatus = -1;

                //没库存，盘盈
                if (stock.getPackageQty() <= 0 ){
                    checkStatus = 1;
                    msg = "盘盈【无库存】";
                }
            }else {
                int count = stockCheckItemService.count(Wrappers.<StockCheckItem>query().ne("check_status","-9").eq("check_id",checkId).eq("stock_id",stock.getId()));
                if (count >0) throw new BusinessException("该唯一码【%s】已盘点过，请勿重复操作",uc);
                msg = "盘亏【无库存记录】";
                stockCheckItem=stockCheckItemService.getOne(Wrappers.<StockCheckItem>query().eq("check_id",checkId).eq("stock_id",stock.getId()));
                if (stockCheckItem == null) {
                    stockCheckItem = new StockCheckItem();
                }
                stockCheckItem.setSn(uc).setStockId("-1").setLineId("-1").setSupplierId("-1").setSupplierName("未知").setMatrName("未知");
                checkStatus = -1;
            }
        }else { //有库存
            int count = stockCheckItemService.count(Wrappers.<StockCheckItem>query().ne("check_status","-9").eq("check_id",checkId).eq("stock_id",stock.getId()));
            if (count >0) throw new BusinessException("该唯一码【%s】已盘点过，请勿重复操作",stock.getSn()== null ?stock.getRfid():stock.getSn());
            stockCheckItem=stockCheckItemService.getOne(Wrappers.<StockCheckItem>query().eq("check_id",checkId).eq("stock_id",stock.getId()));
            if (stockCheckItem == null) {
                stockCheckItem = new StockCheckItem();
                BeanUtils.copyProperties(stock, stockCheckItem);
            }
            if (StringUtils.isNotBlank(stockCheck.getLocationId())) { //库位盘点
                if (!stock.getLocationId().equals(stockCheck.getLocationId())) { //不同库位
                    stockCheckItem.setCheckStatus(1);
                    msg = "盘盈【不同库位】，该唯一码库存所在库位为："+stock.getLocationName();
                    checkStatus = 1;
                }
            }else { //仓库盘点
                if (!stock.getWarehouseId().equals(stockCheck.getWarehouseId())) { //不同仓库
                    stockCheckItem.setCheckStatus(1);
                    msg = "盘盈【不同仓库】，该唯一码库存所在仓库为："+stock.getWarehouseName();
                    checkStatus =1;
                }
            }
        }

        stockCheckItem.setCheckStatus(checkStatus).setCheckId(checkId).setStockId(stock.getId());
        stockCheckItemService.saveOrUpdate(stockCheckItem);

        restResult.setMsg(msg);

        //更新盘盈盘亏未知
        restResult.setData(this.updateMain(stockCheck));
        return restResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResult RFIDScan(List<String> ucs, String checkId) {
        long beginTime = System.currentTimeMillis();
        RestResult restResult = RestResult.ok();
        //截取尾部F
        List<String> ucList = ucs.stream().flatMap(s -> {
            String rfid = selectF(s);
            return Stream.of(rfid);
        }).collect(Collectors.toList());
        StockCheck stockCheck = this.getById(checkId);//获取当前盘点单对应的库存盘点单信息
        String msgBuffer = "";
        //盘点状态 0：正常 1：盘盈 -1：盘亏 ， -9： 未盘， -2：重复盘点
        int numLoss = 0, numSurplus = 0, numUnknown = 0, numNormal = 0, numNrepetitive = 0;
        if (stockCheck == null) throw new BusinessException("所操作的盘点单不存在或者已被删除");
        if (stockCheck.getFlagFinished() != null && stockCheck.getFlagFinished()) {
            throw new BusinessException("该盘点单【%s】已结束盘点，请勿重复操作", stockCheck.getBusKey());
        }
        //        查询盘库单明细
        List<StockCheckItem> stockCheckItems = stockCheckItemService.list(Wrappers.<StockCheckItem>query().eq("check_id", checkId).in("rfid", ucList));
        //        过滤掉当前盘库单中未盘明细得到已盘的
        List<StockCheckItem> checkedItemList = stockCheckItems.stream().filter(s -> s.getCheckId().equals(checkId)).filter(stockCheckItem -> stockCheckItem.getCheckStatus() != -9).collect(Collectors.toList());
        List<StockCheckItem> uncheckItemList = stockCheckItems.stream().filter(s -> s.getCheckId().equals(checkId)).filter(stockCheckItem -> stockCheckItem.getCheckStatus() == -9).collect(Collectors.toList());

        if (ParameterUtils.isStockcheckUseview()) { //HRP系统
            // 从HRP系统查询本次扫描到的RFID列表对应的库存--这些扫描到的RFID并不一定都在库存中
            List<HrpStockItemDTO> hrpStockItemDTOList = hrpService.getStockItem(ucList);
            List<String> rfidList = hrpStockItemDTOList.stream().map(HrpStockItemDTO::getRfid).collect(Collectors.toList());

            if (CollectionUtils.isNotEmpty(hrpStockItemDTOList)) {
                //获取到能够查到库内的耗材的RFID列表
                List<String> rfids = hrpStockItemDTOList.stream().filter(s->StringUtils.isNotBlank(s.getRfid())).map(HrpStockItemDTO::getRfid).collect(Collectors.toList());
                List<String> warehouseCodes = hrpStockItemDTOList.stream().map(HrpStockItemDTO::getWarehouseCode).collect(Collectors.toList());
                //            相同的rfid集合rfids
                rfids.retainAll(ucList);//取得两个List的交集

            /*List<Warehouse> warehouseList = warehouseService.list(Wrappers.<Warehouse>query().in("hrp_code", warehouseCodes));
            if (warehouseList == null || warehouseList.size() == 0) {
                throw new BusinessException("hrp库存编码未维护，请检查！");
            }*/
                //            遍历有HRP库存记录数据
                for (String rfid : rfids) {//rfids都是能查到对应的库存的
                    Optional<HrpStockItemDTO> stockItemDTO = hrpStockItemDTOList.stream().filter(s->StringUtils.isNotBlank(s.getRfid())).filter(s -> s.getRfid().equals(rfid)).findFirst();
                    if (stockItemDTO.isPresent()) {
                        //
                        int num = hrpStockCheck(rfid, checkId, stockCheck, checkedItemList, stockItemDTO.get(),uncheckItemList);
                        if (num == 0) {
                            numNormal++;
                        }
                        if (num == -1) {
                            numLoss++;
                        }
                        if (num == 1) {
                            numSurplus++;
                        }
                        if (num == -9) {
                            numUnknown++;
                        }
                        if (num == -2) {
                            numNrepetitive++;
                        }
                    }
                }
            }
            int normal = stockCheckItemService.count(Wrappers.<StockCheckItem>query().eq("check_id", checkId).eq("check_status", 0));
            if (normal == stockCheck.getStockNum()) {//理论库存已经全部被盘出来了
                msgBuffer = ", 该盘点单对应的盘点明细已经全部盘完，请核对盘点信息";
            } else {
                ucList.removeAll(rfidList);

                // 无HRP库存记录
                if (!ucList.isEmpty()) {
                    List<StockCheckItem> checkedSurplusItems = stockCheckItemService.list(Wrappers.<StockCheckItem>query().eq("check_id", checkId).in("rfid",ucList).eq("check_status", 1));
                    for (String rfid : ucList) {
                        int num = noStockCheckforHRP(rfid, checkId, checkedSurplusItems);
                        if (num == 1) {
                            numSurplus++;
                        }
                        if (num == -2) {
                            numNrepetitive++;
                        }
                    }
                }
            }


            if (normal < stockCheck.getStockNum() && CollectionUtils.isEmpty(hrpStockItemDTOList)) {
                msgBuffer = ", 本次扫描的RFID未查询到库存数据，请检查库存视图或者移动盘点位置";
            }



        }
        if (!ParameterUtils.isStockcheckUseview()) { //SPD系统--暂时没有其他医院在用手持的RFID库存盘点
            throw new BusinessException("手持的RFID库存盘点,暂不支持SPD库存盘点，后期完善敬请期待");
//            查询RFID所有库存
            /*List<Stock> stockList = stockService.list(Wrappers.<Stock>query().in("rfid", ucList));
//            能插询到的RFID集合
            List<String> rfids = stockList.stream().map(Stock::getRfid).collect(Collectors.toList());

//            去除存在库存中的的RFID
            ucList.removeAll(rfids);

            if (!ucList.isEmpty()) {
                for (String rfid : ucList) {
                    int num = noStockCheck(rfid, checkId, checkedItemList);
                    if (num == -1) {
                        numLoss++;
                    }
                    if (num == -2) {
                        numNrepetitive++;
                    }
                }
            }

            for (Stock stock : stockList) {
                int num = spdStockCheck(stock.getRfid(), checkId, stockCheck, checkedItemList, stock);
                if (num == 0) {
                    numNormal++;
                }
                if (num == -1) {
                    numLoss++;
                }
                if (num == 1) {
                    numSurplus++;
                }
                if (num == -9) {
                    numUnknown++;
                }
                if (num == -2) {
                    numNrepetitive++;
                }
            }*/
        }
        long endTime = System.currentTimeMillis();
        String ms = DateUtils.formatTime(endTime - beginTime);
        String msg = String.format("正常：%s个，盘亏：%s个，盘盈：%s个，未盘：%s个，重复：%s个，耗时：%s", numNormal, numLoss, numSurplus, numUnknown, numNrepetitive, ms);
        //更新盘盈盘亏未知
        restResult.setMsg(msg + msgBuffer);
        restResult.setData(this.updateMain(stockCheck));
        return restResult;
    }

    private int noStockCheck(String rfid, String checkId, List<StockCheckItem> stockCheckItems) {
        StockCheckItem stockCheckItem = new StockCheckItem();
        long count = stockCheckItems.stream().filter(s -> s.getRfid().equals(rfid)).count();
        if (count > 0) {  //重复盘点
            return -2;
        }
        stockCheckItem.setRfid(rfid).setStockId("-1").setLineId("-1").setSupplierId("-1").setSupplierName("未知").setMatrName("未知");
        stockCheckItem.setCheckStatus(-1).setCheckId(checkId);
        stockCheckItemService.saveOrUpdate(stockCheckItem);
        return -1;
    }
    //扫描出的不在hrp数据视图中的RFID列表盘盈或者重复判断
    private int noStockCheckforHRP(String rfid, String checkId, List<StockCheckItem> checkedSurplusItems) {
        StockCheckItem stockCheckItem = new StockCheckItem();
        long count = checkedSurplusItems.stream().filter(s -> s.getRfid().equals(rfid)).count();
        if (count > 0) {  //重复盘点
            return -2;
        }
        stockCheckItem.setRfid(rfid).setStockId("-1").setLineId("-1").setSupplierId("-1").setSupplierName("未知").setMatrName("未知");
        stockCheckItem.setCheckStatus(1).setCheckId(checkId);
        stockCheckItemService.saveOrUpdate(stockCheckItem);
        return 1;
    }

    private int hrpStockCheck(String rfid, String checkId, StockCheck stockCheck, List<StockCheckItem> stockCheckedItems, HrpStockItemDTO hrpStock, List<StockCheckItem> unCheckItems) {
        StockCheckItem stockCheckItem = new StockCheckItem();
        int checkStatus = 0;//盘点状态 0：正常 1：盘盈 -1：盘亏 ， -9： 未盘， -2：重复盘点
        long count = stockCheckedItems.stream().filter(s -> s.getRfid().equals(rfid)).count();
        if (count > 0) {  //重复盘点
            return -2;
        }
        List<StockCheckItem> thisCheckItems = unCheckItems.stream().filter(s -> s.getRfid().equals(rfid)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(thisCheckItems)) {
            stockCheckItem =  thisCheckItems.get(0);//由于是一物一码，就取第一个
            //理论上在库中对应的无库存数量
            if (hrpStock.getPackageQty() < 1) {
                checkStatus = 1;//数据库里面没有，结果实物有，则是盘盈  1：盘盈
            } else { //有库存数量
                checkStatus = 0;//如果存在说明该实物是正常的
            }
        } else {//防止数据出错，对应的RFID查到的数据被删掉了，这时我们只认为它是盘盈的
            BeanUtils.copyProperties(hrpStock, stockCheckItem);
            stockCheckItem.setRfid(rfid);
            checkStatus = 1;//数据库里面没有，结果实物有，则是盘盈  1：盘盈
        }

        stockCheckItem.setCheckStatus(checkStatus).setCheckId(checkId);
        stockCheckItemService.saveOrUpdate(stockCheckItem);
        return checkStatus;
    }

    private int spdStockCheck(String uc, String checkId, StockCheck stockCheck, List<StockCheckItem> stockCheckItems, Stock stock) {
        StockCheckItem stockCheckItem = new StockCheckItem();
        int checkStatus = 0;
//            无库存数量
        if (stock.getPackageQty() < 1) {
            long count = stockCheckItems.stream().filter(s -> s.getRfid().equals(uc)).count();
            if (count > 0) {  //重复盘点
                return -2;
            }
            Optional<StockCheckItem> optional = stockCheckItems.stream().filter(s -> s.getRfid().equals(uc)).findFirst();
            if (!optional.isPresent()) {
                stockCheckItem = new StockCheckItem();
                BeanUtils.copyProperties(stock, stockCheckItem);
            }
            checkStatus = -1;
        } else { //            有库存数量
            long count = stockCheckItems.stream().filter(s -> s.getRfid().equals(uc)).count();
            if (count > 0) {  //重复盘点
                return -2;
            }
            Optional<StockCheckItem> optional = stockCheckItems.stream().filter(s -> s.getRfid().equals(uc)).findFirst();
            if (!optional.isPresent()) {
                stockCheckItem = new StockCheckItem();
                BeanUtils.copyProperties(stock, stockCheckItem);
            }
            if (StringUtils.isNotBlank(stockCheck.getLocationId())) { //库位盘点
                if (!stock.getLocationId().equals(stockCheck.getLocationId())) { //不同库位
                    checkStatus = 1;
                }
            } else { //仓库盘点
                if (!stock.getWarehouseId().equals(stockCheck.getWarehouseId())) { //不同仓库
                    checkStatus = 1;
                }
            }
        }
        stockCheckItem.setCheckStatus(checkStatus).setCheckId(checkId);
        stockCheckItemService.saveOrUpdate(stockCheckItem);
        return checkStatus;
    }
    private StockCheck updateMain(StockCheck stockCheck) {
        List<StockCheckItem> stockCheckItems = stockCheckItemService.list(new QueryWrapper<StockCheckItem>().eq("check_id", stockCheck.getId()));
        //盘点状态 0：正常 1：盘盈 -1：盘亏 -9：未盘
        stockCheck.setStockNormal(Double.valueOf(stockCheckItems.stream().filter(item -> item.getCheckStatus() == 0).count()));
        stockCheck.setStockLoss(Double.valueOf(stockCheckItems.stream().filter(item -> item.getCheckStatus() == -1).count()));
        stockCheck.setStockSurplus(Double.valueOf(stockCheckItems.stream().filter(item -> item.getCheckStatus() == 1).count()));
        stockCheck.setStockUnknown(Double.valueOf(stockCheckItems.stream().filter(item -> item.getCheckStatus() == -9).count()));
        this.updateById(stockCheck);
        return stockCheck;
    }



    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {
        for (Serializable id : idList) {
            List<StockCheckItem> items = stockCheckItemService.list(Wrappers.<StockCheckItem>query().select("id").eq("check_id", id));
            if (items != null && items.size() > 0) stockCheckItemService.removeCascadeByIds(items.stream().map(o -> o.getId()).collect(Collectors.toList()));
        }
        return super.removeCascadeByIds(idList);
    }


    @Override
    public boolean removeCascadeById(Serializable id) {
        return this.removeCascadeByIds(Arrays.asList(id));
    }

    private static String selectF(String s) {
        String s1 = s;
        if (s.endsWith("F")) {
            s1 = selectF(s.substring(0, s.lastIndexOf("F")));
        }
        return s1;
    }
}
